﻿
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace SuperGo.SilverlightLib.Sgf {
    internal class SgfTokenizer {
        private string Data { get; set; }
        public int Row { get; private set; }
        public int Column { get; private set; }
        public SgfToken Current { get; private set; }

        public SgfTokenizer(TextReader reader) {
            Data = reader.ReadToEnd();
            Current = null;
            Row = 1;
            Column = 1;
        }

        public void Chomp(string str) {
            ChompWhiteSpace();
            if (!StartsWith(str)) {
                throw new SgfTokenizerException("Invalid string at {0}:{1}... Expecting '{2}'. Found '{3}'", Row, Column, str, Data.Substring(0, Math.Min(Data.Length, str.Length)));
            }
            for (int i = 0; i < str.Length; i++) {
                char ch = Data[0];
                if (ch == '\n') {
                    Row++;
                    Column = 1;
                } else {
                    Column++;
                }
                Data = Data.Substring(1);
            }
        }

        private void ChompWhiteSpace() {
            for (int i = 0; i < Data.Length; i++) {
                char ch = Data[0];
                if (char.IsWhiteSpace(ch)) {
                    if (ch == '\n') {
                        Row++;
                        Column = 1;
                    } else {
                        Column++;
                    }
                } else {
                    break;
                }
                Data = Data.Substring(1);
            }
        }

        public SgfToken Chomp(SgfToken token) {
            ChompWhiteSpace();
            Match match = token.Regex.Match(Data);
            if (!match.Success) {
                throw new SgfTokenizerException("Invalid string at {0}:{1}... Expecting token '{2}'", Row, Column, token.Index);
            }
            SgfToken result = token.CloneWithValue(match.Value);
            Chomp(result.Value);
            return result;
        }

        public SgfToken Chomp(SgfToken[] tokens) {
            ChompWhiteSpace();
            int? maxToken = null;
            int maxLength = -1;
            for (int i = 0; i < tokens.Length; i++) {
                Match match = tokens[i].Regex.Match(Data);
                if (match.Success) {
                    if (match.Length > maxLength) {
                        maxLength = match.Length;
                        maxToken = i;
                    }
                }
            }
            if (maxToken == null) {
                StringBuilder tokenList = new StringBuilder();
                for (int i = 0; i < tokens.Length; i++) {
                    if (i > 0) {
                        tokenList.Append(", ");
                    }
                    tokenList.Append(tokens[i].Index);
                }
                throw new SgfTokenizerException("Invalid string at {0}:{1}... Expecting one of token '{2}'", Row, Column, tokenList);
            }
            SgfToken result = Chomp(tokens[maxToken.Value]);
            return result;
        }

        public bool StartsWith(string str) {
            ChompWhiteSpace();
            return Data.StartsWith(str);
        }

        public bool StartsWith(SgfToken token) {
            ChompWhiteSpace();
            Match match = token.Regex.Match(Data);
            return match.Success;
        }
    }
}
